using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public enum State
{
	playblack=0,
	playwhite=1,
	mainmenu=2,
	singlemenu=3,
	multimenu=4,
	ingamemenu=5,
	whitewon=6,
	blackwon=7,
	tiegame=8,
	quitgame=9,
	waitingforplayer=10,
	waitingforserver=11,
	connectfailed=12
}

public enum Type
{
	single=0,
	multi=1,
	hotseat=2
}

public class gameManager : MonoBehaviour {
	
	public int currentState;
	public int gameType;
	public GUISkin currentSkin;
	
	private List<int> stateStack = new List<int>();
	private boardManager BM;
	private netManager NM;
	private float screenW;
	private float screenH;
	private Rect rectDialogBox;
	private Rect rectTopBanner;
	private Rect rectMenuWindow;
	

	
	private void Start()
	{
		gameType = (int)Type.hotseat;
		PushState((int)State.mainmenu);
		BM = GameObject.Find("World").GetComponent<boardManager>();
		if(!BM)
		{
			Debug.LogError("boardManager not found.  Add a boardManager to World.");
		}
		NM = GameObject.Find("World").GetComponent<netManager>();
		if(!NM)
		{
			Debug.LogError("netManager not found.  Add a boardManager to World.");
		}
		UpdateRectangles();

	}
	
	public void StartNewGame()
	{
		BM.StartNewBoard();
		ClearState();
		if(gameType==(int)Type.hotseat)
		{
			PushState((int)State.playblack);
			
		} 
		if(gameType==(int)Type.multi)
		{
			
			if (Network.connections.Length == 0) {
				// we don't have any clients yet
				PushState((int)State.waitingforplayer);
				NM.LaunchServer();
			} else {
				// we already have a client
				// tell them to reset too
				NM.ResetClient();
				PushState((int)State.playblack);
			}
			
		}
		if(gameType==(int)Type.single)
		{
			PushState((int)State.playblack);
			
		} 
		
		
	}
	
	public void SendClick(RPCMode mode, int index)
	{
		NM.SendClick(mode, index);
	}

	[RPC]
	public void ClientReset()
	{
		BM.StartNewBoard();
		ClearState();
		PushState((int)State.playblack);
	}
	
	public void PushStateToClient(int i)
	{
		NM.ResetClient();
		NM.PushStateClient(i);
	}
	
	[RPC]
	public void ClientPushState(int i)
	{
		PushState(i);
	}
	
	public void ConnectNetworkGame()
	{
		StartNewGame();
		NM.ConnectToServer();
		gameType = (int)Type.multi;
	}
	
	public int GetLocalPlayer()
	{
		return BM.localPlayer;
	}
	
	public void SetGameType(int i)
	{
		gameType = i;
	}
		
	public void PushState(int i)
	{
		// push the requested state
		// to the top of the stack
		
		stateStack.Add(i);
		currentState = i;
		
	}
	public void PopState()
	{
		// pop the top element off
		// the stack and revert the
		// game state to the previous
		// state
		
		int count = stateStack.Count;
		if(count>1)
		{
			stateStack.RemoveAt(count-1);
			count--;
			currentState = stateStack[count-1];
		} else {
			Debug.LogError("Tried to remove a state from an empty state stack");
		}
	}
	public void ReplaceState(int i)
	{
		// replace the top state on the 
		// state stack with the provided
		// state - used for one-way state
		// transitions like going from
		// playing the game to winning the
		// game
		
		int count = stateStack.Count;
		if(count > 0)
		{
			stateStack.RemoveAt(count-1);
		} 
		
		PushState(i);
	}
	
	public void ClearState()
	{
		stateStack.Clear();
	}
	
	public void EscapeState()
	{
		
		switch(currentState)
		{
		case (int)State.playblack:
			PushState((int)State.ingamemenu);
			break;
		case (int)State.playwhite:
			PushState((int)State.ingamemenu);
			break;
		case (int)State.mainmenu:
			PushState((int)State.quitgame);
			break;
		case (int)State.singlemenu:
			PopState();
			break;
		case (int)State.multimenu:
			PopState();
			break;
		case (int)State.ingamemenu:
			PopState();
			break;
		case (int)State.quitgame:
			PopState();
			break;
		// escape is ignored in
		// any of the win game state
		}
	}
	
		void UpdateRectangles()	
	{
		// this function updates the
		// rectangles used to draw GUI
		// content, this can be called
		// anytime a change in the screen
		// resolution is detected
		
		screenW = (float)Screen.width;
		screenH = (float)Screen.height;
		rectDialogBox = new Rect(screenW * 0.35F, screenH * 0.25F, screenW * 0.3F, screenH * 0.25F);
		rectTopBanner = new Rect(screenW * 0.25F, 8.0F, screenW * 0.5F, screenH * 0.1F);
		rectMenuWindow = new Rect(screenW * 0.25F, screenH * 0.15F, screenW * 0.50F, screenH * 0.70F);

	}

	void OnGUI() 
	{
		GUI.skin = currentSkin;
		
		switch(currentState){
			
		case (int)State.playblack:
			DrawPlay((int)State.playblack);
			break;
			
		case (int)State.playwhite:
			DrawPlay((int)State.playwhite);
			break;
			
		case (int)State.waitingforplayer:
			DrawWaiting();
			break;
		case (int)State.waitingforserver:
			DrawWaiting();
			break;

		case (int)State.mainmenu:
			rectMenuWindow = GUI.Window(0,rectMenuWindow,DrawMainMenuWindow,"");
			break;
			
		case (int)State.singlemenu:
			rectMenuWindow = GUI.Window(0,rectMenuWindow,DrawSingleMenuWindow,"");
			break;
			
		case (int)State.multimenu:
			rectMenuWindow = GUI.Window(0,rectMenuWindow,DrawMultiMenuWindow,"");
			break;
			
		case (int)State.ingamemenu:
			rectMenuWindow = GUI.Window(0,rectMenuWindow,DrawInGameMenuWindow,"");
			break;
		
		// everything else is a simple dialog box
		// and the contents are determined
		// by the DrawDialogWindow function itself
			
		default:
			rectDialogBox = GUI.Window(2,rectDialogBox,DrawDialogWindow,"");
			break;
			
			
		}
	}
	
	
	void DrawMainMenuWindow(int windowID)
	{
		GUI.DragWindow(new Rect(0,0,1000,20));
		if(GUILayout.Button("Single Player Game"))
		{
			PushState((int)State.singlemenu);
		}
		if(GUILayout.Button("Multiplayer Game"))
		{
			PushState((int)State.multimenu);
		}
		if(GUILayout.Button("Quit Game"))
		{
			Application.Quit();
		}
	}
	
	void DrawSingleMenuWindow(int windowID)
	{
		// This is for games vs. the computer
		
		GUI.DragWindow(new Rect(0,0,1000,20));
		
		// Load Level List will be here
		if(GUILayout.Button("Load Saved Game"))
		{
		}
		if(GUILayout.Button("Rename Game"))
		{
		}
		if(GUILayout.Button("Delete Game"))
		{
		}
		if(GUILayout.Button("Start New Game"))
		{
			SetGameType((int)Type.single);
			StartNewGame();
		}
		if(GUILayout.Button("Cancel"))
		{
			PopState();
		}

	}
	
	
	void DrawMultiMenuWindow(int windowID)
	{
		GUI.DragWindow(new Rect(0,0,1000,20));
		
		GUILayout.BeginHorizontal();
		GUILayout.Label("Server IP Address: ");
		NM.serverAddress=GUILayout.TextField(NM.serverAddress,15);
		GUILayout.EndHorizontal();
		
		GUILayout.BeginHorizontal();
		GUILayout.Label("Server Port: ");
		NM.serverPort=int.Parse(GUILayout.TextField(NM.serverPort.ToString(),15));
		GUILayout.EndHorizontal();
		
		NM.LANOnly = GUILayout.Toggle(NM.LANOnly,"Home Network Only");
		
		if(GUILayout.Button("Hot Seat Game"))
		{
			SetGameType((int)Type.hotseat);
			StartNewGame();
		}

		if(GUILayout.Button("Join Network Game"))
		{
			ConnectNetworkGame();
		}
		if(GUILayout.Button("Host Network Game"))
		{
			SetGameType((int)Type.multi);
			StartNewGame();
		}
		if(GUILayout.Button("Cancel"))
		{
			PopState();
		}

	}
	


	void DrawInGameMenuWindow(int windowID)
	{
		GUI.DragWindow(new Rect(0,0,1000,20));
		if(GUILayout.Button("Return to Game"))
		{
			PopState();
		}
		if(GUILayout.Button("Save Game"))
		{
		}

		if(GUILayout.Button("Start Over"))
		{
			StartNewGame();
		}
		if(GUILayout.Button("Return to Main Menu"))
		{
			StartNewGame();
			PushState((int)State.mainmenu);
			PushStateToClient((int)State.mainmenu);
		}
		if(GUILayout.Button("Quit Game"))
		{
			Application.Quit();
		}

	}
	
	void DrawDialogWindow(int windowID)
	{
		// make just the top 20 pixels of 
		// the window activate dragging
		GUI.DragWindow(new Rect(0,0,1000,20));
		
		// now add content for the window
		// based on the game state
		
		switch(currentState){
			
		case (int)State.connectfailed:
			GUILayout.Label("Connection to server failed.");
			GUILayout.BeginHorizontal();
			if(GUILayout.Button("Cancel"))
			{
				ClearState();
				PushState((int)State.mainmenu);
			}
			if(GUILayout.Button("Retry"))
			{
				ClearState();
				PushState((int)State.mainmenu);
				PushState((int)State.multimenu);
			}
			GUILayout.EndHorizontal();
			
			break;
			
		case (int)State.quitgame:
			GUILayout.Label("Are you sure you\nwant to quit?");
			GUILayout.BeginHorizontal();
			if(GUILayout.Button("No"))
			{
				PopState();
			}
			if(GUILayout.Button("Yes"))
			{
				Application.Quit();
			}
			GUILayout.EndHorizontal();
			break;
		
		case (int)State.whitewon:
			
			GUILayout.Label("WHITE WON !!!\nWould you like to play again?");
			GUILayout.BeginHorizontal();
			if(GUILayout.Button("No"))
			{
				Application.Quit();
			}
			if(GUILayout.Button("Yes"))
			{
				StartNewGame();
			}
			GUILayout.EndHorizontal();
			break;
			
		case (int)State.blackwon:
			GUILayout.Label("BLACK WON !!!\nWould you like to play again?");
			GUILayout.BeginHorizontal();
			if(GUILayout.Button("No"))
			{
				Application.Quit();
			}
			if(GUILayout.Button("Yes"))
			{
				StartNewGame();
			}
			GUILayout.EndHorizontal();
			break;
			
		case (int)State.tiegame:
			GUILayout.Label("TIE GAME !!!\nWould you like to play again?");
			GUILayout.BeginHorizontal();
			if(GUILayout.Button("No"))
			{
				Application.Quit();
			}
			if(GUILayout.Button("Yes"))
			{
				StartNewGame();
			}
			GUILayout.EndHorizontal();
			break;
		}
		
	}

	void DrawWaiting()
	{
		// create a top-banner area
		GUILayout.BeginArea(rectTopBanner);
		
		GUILayout.Label("Waiting for other player to join...");
		
		GUILayout.EndArea();
	}

	void DrawPlay(int side)
	{
		// create a top-banner area
		GUILayout.BeginArea(rectTopBanner);
		
		if(gameType==(int)Type.hotseat){
			if(side==(int)Stone.black)
			{
				GUILayout.Label("Black's Turn");
			} else {
				GUILayout.Label("White's Turn");
			}

		} else {
			if(side==BM.localPlayer)
			{
				GUILayout.Label("Your Turn");
			} else {
				GUILayout.Label("Opponent's Turn");
			}
			if(side==(int)Stone.black)
			{
				GUILayout.Label("(Black)");
			} else {
				GUILayout.Label("(White)");
			}
			
		}
		GUILayout.BeginHorizontal();
		GUILayout.Label("Black Stones: " + BM.currentBlackStones.ToString());
		GUILayout.Label("White Stones: " + BM.currentWhiteStones.ToString());
		GUILayout.EndHorizontal();
		GUILayout.EndArea();
	}
	

}
